using DJLang;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;

public class ToJsonExample : MonoBehaviour
{
    public TextAsset text;
    private void Awake()
    {
        var env = new DJEnv();
        env.PutLibrary(typeof(ToJsonLib));
        using var reader = new DJReader(new StringReader(text.text));
        Debug.Log(reader.EvaluateToEnd(env).GetManaged<string>());
    }
}

public static class ToJsonLib
{
    [DJFunc("json")]
    public static IDJValue DJToJson(DJEnv env, DJSeq args)
    {
        var json = args.PopAs<DJList>();
        return new DJString(ToJson(json));
    }

    private static string ToJson(IDJValue value) => value switch
    {
        DJBasic<bool> b => b.val.ToString().ToLower(),
        DJInt i => i.val.ToString(),
        DJFloat f => f.val.ToString(),
        DJString s => $"\"{s.val}\"",
        DJList list => DJListToJson(list),
        _ => "null"
    };

    private static string DJListToJson(DJList list)
    {
        if (list.Peek() is DJList)
        {
            var builder = new StringBuilder();
            builder.Append("{");
            while (list.Count > 0)
            {
                var pair = list.PopAs<DJList>();
                var name = pair.PopAs<DJSymbol>();
                var value = pair.Pop();
                builder.Append(ConvertName(name.name));
                builder.Append(":");
                builder.Append(ToJson(value));
                if (list.Count != 0) builder.Append(",");
            }
            builder.Replace('-', '_');
            builder.Append("}");
            return builder.ToString();
        }
        else
        {
            return $"[{string.Join(',', list.Select(x => ToJson(x)))}]";
        }
    }

    private static string ConvertName(string name)
    {
        var builder = new StringBuilder(name);
        builder.Replace('-', '_');
        if (name.EndsWith('?'))
        {
            builder.Remove(builder.Length - 1, 1);
            builder.Insert(0, "is_");
        }
        return $"\"{builder}\"";
    }
}